package com.note.common.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.note.common.annotation.GatewayOnly;
import com.note.common.vo.ResponseVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 网关访问拦截器
 * 根据GatewayOnly注解拦截请求，确保只能通过网关访问
 */
@Slf4j
public class GatewayOnlyInterceptor implements HandlerInterceptor {

    private final ObjectMapper objectMapper;
    private final String gatewayHeader;
    private final String gatewaySecret;
    private final boolean enabled;

    /**
     * 构造函数
     * 
     * @param objectMapper 用于JSON序列化
     * @param gatewayHeader 网关请求头名称
     * @param gatewaySecret 网关请求头密钥
     * @param enabled 是否启用网关检查
     */
    public GatewayOnlyInterceptor(
            ObjectMapper objectMapper,
            String gatewayHeader,
            String gatewaySecret,
            boolean enabled) {
        this.objectMapper = objectMapper;
        this.gatewayHeader = gatewayHeader;
        this.gatewaySecret = gatewaySecret;
        this.enabled = enabled;
        log.info("创建GatewayOnlyInterceptor: header={}, enabled={}", gatewayHeader, enabled);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果全局禁用了检查，直接放行
        if (!enabled) {
            return true;
        }

        // 只处理带有方法的处理器
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Class<?> clazz = handlerMethod.getBeanType();

        // 判断方法或类上是否有GatewayOnly注解
        GatewayOnly methodAnnotation = method.getAnnotation(GatewayOnly.class);
        GatewayOnly classAnnotation = clazz.getAnnotation(GatewayOnly.class);

        if (methodAnnotation != null && !methodAnnotation.enabled()) {
            // 方法级注解禁用了检查，放行
            return true;
        }

        if (methodAnnotation == null && (classAnnotation == null || !classAnnotation.enabled())) {
            // 没有任何启用的注解，放行
            return true;
        }

        // 需要进行网关检查
        String gatewayValue = request.getHeader(gatewayHeader);
        if (gatewaySecret.equals(gatewayValue)) {
            // 请求来自网关，放行
            return true;
        }

        // 拒绝访问
        response.setStatus(HttpStatus.FORBIDDEN.value());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");

        ResponseVo<Void> responseVo = ResponseVo.error(
                HttpStatus.FORBIDDEN.value(),
                "禁止直接访问，请通过API网关访问");

        String jsonResponse = objectMapper.writeValueAsString(responseVo);
        response.getWriter().write(jsonResponse);
        return false;
    }
} 